// 装饰器使用示例

import { RedisToolkit } from '../src';
import { Cache, setCacheManager } from '../src/decorators/cache';
import { RateLimit, setRateLimitManager } from '../src/decorators/rateLimit';
import { Lock, setLockManager } from '../src/decorators/lock';

// 创建Redis Toolkit实例
const redis = new RedisToolkit({
  host: process.env['REDIS_HOST'] || 'localhost',
  port: parseInt(process.env['REDIS_PORT'] || '6379'),
  autoSerialize: true,
});

// 设置装饰器管理器
setCacheManager(redis.cache);
setRateLimitManager(redis.rateLimit);
setLockManager(redis.lock);

// 用户服务类 - 演示缓存装饰器
class UserService {
  /**
   * 获取用户信息 - 使用缓存装饰器
   */
  @Cache({ 
    ttl: 300, // 5分钟缓存
    key: 'user:${args[0]}',
    tags: ['user'] 
  })
  async getUser(userId: string): Promise<any> {
    console.log(`🔍 从数据库获取用户 ${userId}...`);
    
    // 模拟数据库查询延迟
    await new Promise(resolve => setTimeout(resolve, 100));
    
    return {
      id: userId,
      name: `User ${userId}`,
      email: `user${userId}@example.com`,
      createdAt: new Date(),
      lastLogin: new Date(),
    };
  }

  /**
   * 获取用户配置文件 - 带条件的缓存
   */
  @Cache({ 
    ttl: 600,
    key: 'profile:${args[0]}',
    condition: (args) => args[0] !== 'admin', // 管理员不缓存
    tags: ['user', 'profile']
  })
  async getUserProfile(userId: string): Promise<any> {
    console.log(`📋 从数据库获取用户配置 ${userId}...`);
    
    await new Promise(resolve => setTimeout(resolve, 50));
    
    return {
      userId,
      preferences: { theme: 'dark', language: 'zh-CN' },
      settings: { notifications: true, privacy: 'public' },
      updatedAt: new Date(),
    };
  }

  /**
   * 更新用户信息 - 清除相关缓存
   */
  async updateUser(userId: string, data: any): Promise<any> {
    console.log(`✏️ 更新用户 ${userId}...`);
    
    // 模拟数据库更新
    await new Promise(resolve => setTimeout(resolve, 80));
    
    // 手动清除相关缓存
    await redis.cache.invalidateByTag('user');
    
    return { success: true, userId, data };
  }
}

// API控制器类 - 演示限流装饰器
class ApiController {
  /**
   * 用户级别的API限流
   */
  @RateLimit({
    limit: 10,
    window: 60, // 每分钟最多10次
    key: 'api:user:${args[0]}'
  })
  async getUserData(userId: string): Promise<any> {
    console.log(`🌐 处理用户 ${userId} 的API请求...`);
    
    return {
      userId,
      data: 'Some user data',
      timestamp: new Date(),
    };
  }

  /**
   * 全局API限流
   */
  @RateLimit({
    limit: 100,
    window: 60,
    key: 'api:global'
  })
  async getPublicData(): Promise<any> {
    console.log('🌍 处理公共API请求...');
    
    return {
      data: 'Public data',
      timestamp: new Date(),
    };
  }

  /**
   * 高级用户的特殊限流
   */
  @RateLimit({
    limit: 50,
    window: 60,
    key: 'api:premium:${args[0]}',
    type: 'sliding' // 使用滑动窗口
  })
  async getPremiumData(userId: string): Promise<any> {
    console.log(`💎 处理高级用户 ${userId} 的API请求...`);
    
    return {
      userId,
      premiumData: 'Premium content',
      timestamp: new Date(),
    };
  }
}

// 订单服务类 - 演示分布式锁装饰器
class OrderService {
  /**
   * 处理订单 - 使用分布式锁防止重复处理
   */
  @Lock({
    key: 'order:${args[0]}',
    ttl: 30
  })
  async processOrder(orderId: string): Promise<any> {
    console.log(`📦 处理订单 ${orderId}...`);
    
    // 模拟订单处理时间
    await new Promise(resolve => setTimeout(resolve, 2000));
    
    return {
      orderId,
      status: 'processed',
      processedAt: new Date(),
    };
  }

  /**
   * 库存扣减 - 使用可重入锁
   */
  async updateInventory(productId: string, quantity: number): Promise<any> {
    console.log(`📊 更新产品 ${productId} 库存，数量: ${quantity}...`);
    
    // 使用手动锁管理
    const lockToken = await redis.lock.acquire(`inventory:${productId}`, { ttl: 10 });
    
    if (!lockToken) {
      throw new Error('无法获取库存锁，请稍后重试');
    }

    try {
      // 模拟库存检查和更新
      await new Promise(resolve => setTimeout(resolve, 500));
      
      return {
        productId,
        quantity,
        updatedAt: new Date(),
      };
    } finally {
      await redis.lock.release(`inventory:${productId}`, lockToken);
    }
  }
}

// 支付服务类 - 演示多种装饰器组合
class PaymentService {
  /**
   * 处理支付 - 组合使用限流和锁
   */
  @RateLimit({
    limit: 5,
    window: 60,
    key: 'payment:${args[0]}'
  })
  @Lock({
    key: 'payment:process:${args[1]}',
    ttl: 60
  })
  async processPayment(userId: string, paymentId: string, amount: number): Promise<any> {
    console.log(`💳 处理用户 ${userId} 的支付 ${paymentId}，金额: ${amount}...`);
    
    // 模拟支付处理
    await new Promise(resolve => setTimeout(resolve, 1500));
    
    return {
      userId,
      paymentId,
      amount,
      status: 'success',
      processedAt: new Date(),
    };
  }

  /**
   * 获取支付历史 - 带缓存
   */
  @Cache({
    ttl: 1800, // 30分钟
    key: 'payment:history:${args[0]}',
    tags: ['payment', 'history']
  })
  @RateLimit({
    limit: 20,
    window: 60,
    key: 'payment:history:${args[0]}'
  })
  async getPaymentHistory(userId: string): Promise<any> {
    console.log(`📜 获取用户 ${userId} 的支付历史...`);
    
    // 模拟数据库查询
    await new Promise(resolve => setTimeout(resolve, 200));
    
    return {
      userId,
      payments: [
        { id: '1', amount: 100, date: new Date() },
        { id: '2', amount: 200, date: new Date() },
      ],
      total: 300,
    };
  }
}

// 主测试函数
async function decoratorExample() {
  console.log('🎨 开始装饰器使用示例...\n');

  try {
    // 连接Redis
    await redis.connect();
    console.log('✅ Redis连接成功\n');

    // 创建服务实例
    const userService = new UserService();
    const apiController = new ApiController();
    const orderService = new OrderService();
    const paymentService = new PaymentService();

    // 测试缓存装饰器
    console.log('🗄️ 测试缓存装饰器...');
    
    // 第一次调用 - 从数据库获取
    console.log('第一次获取用户:');
    const user1 = await userService.getUser('123');
    console.log('用户信息:', user1.name);
    
    // 第二次调用 - 从缓存获取
    console.log('第二次获取用户 (应该从缓存):');
    const user2 = await userService.getUser('123');
    console.log('用户信息:', user2.name);
    
    // 测试条件缓存
    console.log('获取普通用户配置 (会缓存):');
    await userService.getUserProfile('user123');
    
    console.log('获取管理员配置 (不会缓存):');
    await userService.getUserProfile('admin');
    
    console.log('✅ 缓存装饰器测试完成\n');

    // 测试限流装饰器
    console.log('⏱️ 测试限流装饰器...');
    
    // 测试用户级限流
    console.log('测试用户级限流 (每分钟10次):');
    for (let i = 1; i <= 12; i++) {
      try {
        await apiController.getUserData('user456');
        console.log(`请求 ${i}: 成功`);
      } catch (error) {
        console.log(`请求 ${i}: 被限流 -`, (error as Error).message);
      }
    }
    
    // 测试全局限流
    console.log('测试全局限流:');
    await apiController.getPublicData();
    console.log('全局API请求成功');
    
    console.log('✅ 限流装饰器测试完成\n');

    // 测试分布式锁装饰器
    console.log('🔒 测试分布式锁装饰器...');
    
    // 并发处理同一订单 - 应该只有一个成功
    console.log('并发处理同一订单:');
    const orderPromises = [
      orderService.processOrder('order123'),
      orderService.processOrder('order123'),
      orderService.processOrder('order123'),
    ];
    
    const orderResults = await Promise.allSettled(orderPromises);
    orderResults.forEach((result, index) => {
      if (result.status === 'fulfilled') {
        console.log(`订单处理 ${index + 1}: 成功`);
      } else {
        console.log(`订单处理 ${index + 1}: 失败 -`, result.reason.message);
      }
    });
    
    // 测试手动锁管理
    console.log('测试库存更新:');
    await orderService.updateInventory('product456', 10);
    console.log('库存更新成功');
    
    console.log('✅ 分布式锁装饰器测试完成\n');

    // 测试组合装饰器
    console.log('🎭 测试组合装饰器...');
    
    // 测试支付处理 (限流 + 锁)
    console.log('测试支付处理:');
    const paymentResult = await paymentService.processPayment('user789', 'pay123', 100);
    console.log('支付结果:', paymentResult.status);
    
    // 测试支付历史 (缓存 + 限流)
    console.log('获取支付历史 (第一次):');
    const history1 = await paymentService.getPaymentHistory('user789');
    console.log('支付历史条数:', history1.payments.length);
    
    console.log('获取支付历史 (第二次，应该从缓存):');
    const history2 = await paymentService.getPaymentHistory('user789');
    console.log('支付历史条数:', history2.payments.length);
    
    console.log('✅ 组合装饰器测试完成\n');

    // 清理测试数据
    console.log('🧹 清理测试数据...');
    await redis.cache.clear();
    console.log('✅ 清理完成\n');

    console.log('🎉 装饰器示例全部完成！');
    console.log('💡 装饰器让Redis功能的使用变得更加简洁和优雅！');

  } catch (error) {
    console.error('❌ 装饰器示例失败:', error);
  } finally {
    // 断开连接
    await redis.disconnect();
    console.log('📡 Redis连接已断开');
  }
}

// 运行示例
if (require.main === module) {
  decoratorExample().catch(console.error);
}

export { decoratorExample };
